﻿package rob.skin{
	import rob.data.RGB;
	import rob.data.Vect3d;
	import flash.display.Sprite;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import rob.util.NumberUtil;
	
	public class GouraudSkin{
		private var _colours:Array;
		private var _ratios:Array;
		private var _cMat:Matrix;
		private var _aVDraw:Array, _aUVCoord:Array;
		private var _k:Number;
		
		public function GouraudSkin(aUVCoord:Array,aVDraw:Array):void{
			_aUVCoord = aUVCoord;
			_aVDraw = aVDraw;
			_cMat = new Matrix();
		}
	
		public function setup(lineWeights:Array):void{
			// need to change drawing order, but also lineWeight order based on EDGES
				var tmpVD:Array = _aVDraw.slice(), tmpLW:Array = lineWeights.slice(), j:uint;
				var srt:Array = _aVDraw.sortOn("shade", Array.NUMERIC | Array.RETURNINDEXEDARRAY);
				for(var i:uint in srt){
					_aVDraw[i] = tmpVD[srt[i]];
					j = _edgeToIndex(srt[i],srt[(i+1)%3]);
					lineWeights[i] = tmpLW[j];
				}
				tmpVD = null;
				tmpLW = null;
			// other initial stuff
			_colours = [RGB.grayscale(_aVDraw[0].shade),RGB.grayscale(_aVDraw[2].shade)];
			//_colours = [RGB.redscale(_aVDraw[0].shade),RGB.redscale(_aVDraw[2].shade)];
			_ratios = [0x00,0xFF];
			_k = (_aVDraw[1].shade - _aVDraw[0].shade) / (_aVDraw[2].shade - _aVDraw[0].shade);
		}
		
		private function _updateGouraud():void{
			var p:Array = _aVDraw;
			var p3x:Number, p3y:Number, p4x:Number, p4y:Number, d:Number, p4len:Number;
			
			p3x = p[0].sx + _k * (p[2].sx - p[0].sx);
			p3y = p[0].sy + _k * (p[2].sy - p[0].sy);
			p4x = p[2].sx - p[0].sx;
			p4y = p[2].sy - p[0].sy;
			p4len = Math.sqrt(p4x*p4x + p4y*p4y);
			d = Math.atan2(p3x - p[1].sx, -(p3y - p[1].sy));

			// matrix
			_cMat.identity();
			_cMat.a = Math.cos(Math.atan2(p4y, p4x) - d) * p4len / 1600;
			_cMat.rotate(d);
			_cMat.translate((p[2].sx + p[0].sx) / 2, (p[2].sy + p[0].sy) / 2);			
		}
		
		// now also use normal for different shades...
		public function beginFill(mc:Sprite):void{
			_updateGouraud();
		//trace(_colours);
			mc.graphics.beginGradientFill("linear",_colours,[1,1],_ratios,_cMat);
		}
		
		// [0,1] -> [0], [1,2] -> [1], [0,2] -> [2]
		private function _edgeToIndex(i:uint,j:uint):uint{
			var min:uint = Math.min(i,j), max:uint = Math.max(i,j);
			if(min == 0){
				if(max == 1) return 0; else return 2;
			}
			return 1;
		}
		
		public function get colour():Boolean{ return (_colour == 0) ? false : true;}
		
		public function toString():String{
			return "GouraudSkin: " +name+"("+_textured+",["+_colour+"])";
		}
	}
}